/*
 *  call-seq:
 *     array.hash   -> fixnum
 *
 *  Compute a hash-code for this array. Two arrays with the same content
 *  will have the same hash code (and will compare using <code>eql?</code>).
 */

static VALUE
rb_ary_hash(ary)
    VALUE ary;
{
    long i, h;
    VALUE n;

    h = RARRAY(ary)->len;  #BBT: the length of the array
    for (i=0; i<RARRAY(ary)->len; i++) {  #BBT: for each element of the array
    		#BBT: left-shift h by 1 bit;
    		#     take inclusive OR with second arg
    		#			if h is negative, second arg is 1, else 0
        h = (h << 1) | (h<0 ? 1 : 0);
        n = rb_hash(RARRAY(ary)->ptr[i]);  #BBT: find the hash value of the ith element
        h ^= NUM2LONG(n);  #BBT: bitwise exclusive-OR assignment operator (like +=)
    }
    return LONG2FIX(h);
}

NOTES:
#BBT: & is bit-wise AND; returns true if first bit is set to 1.
#define FIXNUM_P(f) (((long)(f))&FIXNUM_FLAG)

#BBT: right-shift by one bit (losing the FIXNUM_FLAG in the process)
#define FIX2LONG(x) RSHIFT((long)x,1) 

#define NUM2LONG(x) (FIXNUM_P(x)?FIX2LONG(x):rb_num2long((VALUE)x))

#define FIXNUM_FLAG 0x01

#BBT: | is bit-wise inclusive OR; sets the first bit to 1.
#     Perhaps the first bit isn't part of the value for a FIXNUM?
#define LONG2FIX(i) ((VALUE)(((long)(i))<<1 | FIXNUM_FLAG))
